import optuna
import numpy as np
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.metrics import classification_report
from imblearn.over_sampling import SMOTE
from imblearn.under_sampling import TomekLinks
from sklearn.ensemble import RandomForestClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier

from tools.plot_model import plot_singleModel

import warnings

warnings.filterwarnings("ignore")


def best_dt_params(filePath):
    data = pd.read_csv(filePath)
    # print(data)
    column_names = ['loc', 'v(g)', 'ev(g)', 'iv(g)', 'n', 'v', 'l', 'd', 'i', 'e', 'b', 't', 'lOCode', 'lOComment',
                    'lOBlank', 'lOCodeAndComment', 'uniq_Op', 'uniq_Opnd', 'total_Op', 'total_Opnd', 'branchCount']
    # print(column_names)
    df = pd.DataFrame(data=data, columns=column_names)
    # print(df)
    y = pd.DataFrame(data=data, columns=['defects'])
    # print(y)

    # 创建 SMOTE 对象
    smote = SMOTE(sampling_strategy=1.0, random_state=42)  # 1.0 表示将类别1的数量提升到类别0的数量
    # 使用 SMOTE 进行过采样
    X_resampled, y_resampled = smote.fit_resample(df, y)

    # 使用 TomekLinks 进行欠采样
    tl = TomekLinks(sampling_strategy='auto')
    X_resampled, y_resampled = tl.fit_resample(X_resampled, y_resampled)

    # 创建PCA实例并拟合数据
    pca = PCA(n_components=3)  # 选择要保留的主成分数量
    X_pca = pca.fit_transform(X_resampled)  # X是你的特征矩阵

    X_train, X_test, y_train, y_test = train_test_split(X_pca, y_resampled, test_size=0.3)
    # print(X_train)
    # print(y_train)

    X_train = np.array(X_train)
    X_test = np.array(X_test)
    y_train = np.array(y_train)
    y_test = np.array(y_test)
    def objective(trial):
        # 定义参数搜索范围
        n_neighbors = trial.suggest_int("n_neighbors", 1, 200)
        weights = trial.suggest_categorical("weights", ["uniform", "distance"])
        p = trial.suggest_categorical("p", [1, 2])

        # 创建KNN分类器
        knn = KNeighborsClassifier(n_neighbors=n_neighbors, weights=weights, p=p)

        # 训练模型
        knn.fit(X_train, y_train)

        # 使用模型进行预测
        y_pred = knn.predict(X_test)

        # 计算准确性作为优化目标
        f1 = f1_score(y_test, y_pred)

        return f1

    # 创建Optuna的study对象
    study = optuna.create_study(direction="maximize")  # 最大化准确性
    study.optimize(objective, n_trials=1000)  # 运行100次试验

    # 获取最佳参数组合
    best_params = study.best_params
    best_score = study.best_value

    print("最佳参数:", best_params)
    print("最佳准确性:", best_score)


if __name__ == "__main__":
    filePath = "../../data/KC2.csv"
    best_dt_params(filePath)
